package com.quanyan.stadium.service.impl;

import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.quanyan.stadium.api.resp.RespUserGradeIntegral;
import com.quanyan.stadium.api.resp.RespUserGradeIntegralList;
import com.quanyan.stadium.biz.redis.GradeIntegralCacheDao;
import com.quanyan.stadium.constants.GameConstants;
import com.quanyan.stadium.constants.GradePointsConstants;
import com.quanyan.stadium.entity.*;
import com.quanyan.stadium.entity.vo.*;
import com.quanyan.stadium.enums.GameGradeLevelConfigEnum;
import com.quanyan.stadium.enums.GameScheduleScoreEnum;
import com.quanyan.stadium.mapper.*;
import com.quanyan.stadium.service.commonComponent.BaseService;
import com.quanyan.stadium.service.GradeIntegralService;
import com.quanyan.stadium.service.gameLevelScore.GameLevelScoreApi;
import com.quanyan.stadium.service.gameLevelScore.entity.UserFLScoreEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author dongshenglin
 * @date 2016/6/21  19:54
 */
@Service
public class GradeIntegralServiceImpl implements GradeIntegralService {

    @Autowired
    private TbUserIntegralMapper tbUserIntegralMapper;

    @Autowired
    private TbTeamIntegralMapper tbTeamIntegralMapper;

    @Autowired
    private TbGameGradeIntegralMapper tbGameGradeIntegralMapper;

    @Autowired
    private TbIntegralUserHistoryMapper tbIntegralUserHistoryMapper;

    @Autowired
    private TbIntegralTeamHistoryMapper tbIntegralTeamHistoryMapper;

    @Autowired
    private TbGradeStatisticsMapper tbGradeStatisticsMapper;

    @Autowired
    private GradeIntegralCacheDao gradeIntegralCacheDao;

    @Autowired
    private BaseService baseService;

    @Autowired
    private GameLevelScoreApi gameLevelScoreApi;

    @Autowired
    private TbUserGameCollectMapper tbUserGameCollectMapper;

    private final static Logger logger = LoggerFactory.getLogger(GradeIntegralServiceImpl.class);

    @Override
    public List<GradeIntegral> calculateGradePoint(QuaryUserGradePoint quaryUserGradePoint) {
        if(null != quaryUserGradePoint && quaryUserGradePoint.getGradePointLevel() > GameGradeLevelConfigEnum.CONFIG_GAME_GRADE_LEVEL_0.getLabel()){
            Integer categoryId = quaryUserGradePoint.getCategoryId();
            GradePointQuery gradePointQuery = new GradePointQuery();
            gradePointQuery.setK(GradePointsConstants.GRADE_K);
            gradePointQuery.setG(this.calculateG(categoryId, quaryUserGradePoint.getRecordScore()));
            Double gameResult = GameScheduleScoreEnum.getScore(categoryId, quaryUserGradePoint.getGameResult(), (byte) 1);
            List<GradeIntegral> resultIntegral = new ArrayList<>();

            Integer Rm = GradePointsConstants.GRADE_IS_NOT_BADMINTON_RM; //初始值设为非羽毛球

            //小球类比赛
            if(categoryId == GameConstants.CATEGORY_ID_TENNIS || categoryId == GameConstants.CATEGORY_ID_BADMINTON){
                List<GradeIntegral> selfIntegrals = new ArrayList<>();
                if(quaryUserGradePoint.getSelfUserIDs().size()>0){
                    for(Integer uid : quaryUserGradePoint.getSelfUserIDs()){
                        GradeIntegral gradeIntegral = new GradeIntegral();
                        gradeIntegral.setId(uid);
                        gradeIntegral.setIntegral(getUserIntegralTemp(uid, categoryId, quaryUserGradePoint.getGradePointLevel()));
                        selfIntegrals.add(gradeIntegral);
                    }
                }
                if(categoryId == GameConstants.CATEGORY_ID_BADMINTON){ //如果为羽毛球
                    Rm = GradePointsConstants.GRADE_IS_BADMINTON_RM;
                }
                gradePointQuery.setRm(Rm);
                Double self = 0.0;
                for (GradeIntegral selfIntegral : selfIntegrals){
                    self +=selfIntegral.getIntegral();
                }
                Double selfAve = self/selfIntegrals.size();
                List<GradeIntegral> opponentIntegrals = new ArrayList<>();
                if(quaryUserGradePoint.getOpponentUserIDs().size()>0){
                    for(Integer uid : quaryUserGradePoint.getOpponentUserIDs()){
                        GradeIntegral gradeIntegral = new GradeIntegral();
                        gradeIntegral.setId(uid);
                        gradeIntegral.setIntegral(getUserIntegralTemp(uid, categoryId, quaryUserGradePoint.getGradePointLevel()));
                        opponentIntegrals.add(gradeIntegral);
                    }
                }
                Double opponent = 0.0;
                for (GradeIntegral oppontIntegral : opponentIntegrals){
                    opponent += oppontIntegral.getIntegral();
                }
                Double oppontAve = opponent/opponentIntegrals.size();
                Double We_1 = this.calulateWe(selfAve, oppontAve);
                Double We_2 = this.calulateWe(oppontAve, selfAve);

                //本队等级分
                gradePointQuery.setW(gameResult);
                gradePointQuery.setWe(We_1);

                for (GradeIntegral integral : selfIntegrals){
                    this.updateUserIntegral(integral,  quaryUserGradePoint, gradePointQuery, resultIntegral, true);
                }

                //对方队伍等级分
                gradePointQuery.setW(1.0 - gameResult);
                gradePointQuery.setWe(We_2);
                for (GradeIntegral integral : opponentIntegrals){
                    this.updateUserIntegral(integral,  quaryUserGradePoint, gradePointQuery, resultIntegral, false);
                }
            }else  if(categoryId == GameConstants.CATEGORY_ID_FOOTBALL || categoryId == GameConstants.CATEGORY_ID_BASKETBALL){//大球类比赛
                gradePointQuery.setRm(Rm);
                GradeIntegral selfIntegral = new GradeIntegral();
                Integer teamIntegral_1 = this.getTeamIntegral(quaryUserGradePoint.getSelfTeamId(), categoryId);
                selfIntegral.setId(quaryUserGradePoint.getSelfTeamId());
                selfIntegral.setIntegral(teamIntegral_1);

                GradeIntegral opponentIntegral = new GradeIntegral();
                Integer teamIntegral_2 = this.getTeamIntegral(quaryUserGradePoint.getOpponentTeamId(), categoryId);
                opponentIntegral.setId(quaryUserGradePoint.getOpponentTeamId());
                opponentIntegral.setIntegral(teamIntegral_2);

                Double We_1 = this.calulateWe(selfIntegral.getIntegral().doubleValue(), opponentIntegral.getIntegral().doubleValue());
                Double We_2 = this.calulateWe(opponentIntegral.getIntegral().doubleValue(), selfIntegral.getIntegral().doubleValue());

                //本队等级分
                gradePointQuery.setW(gameResult);
                gradePointQuery.setWe(We_1);
                gradePointQuery.setR1(teamIntegral_1);
                Integer self = this.calculateRn(gradePointQuery);
                selfIntegral.setIntegral(self);
                resultIntegral.add(selfIntegral);
                Boolean isWIn_1 = false;
                System.out.print(GradePointsConstants.RESULT_WIN);
                if(new BigDecimal(GradePointsConstants.RESULT_WIN).compareTo(new BigDecimal(gameResult)) == 0){
                    isWIn_1 = true;
                }
                this.updateTeamGrade(selfIntegral.getId(),categoryId,self,quaryUserGradePoint.getGameScheduleId(),isWIn_1);

                //对方队伍等级分
                gradePointQuery.setW(1.0 - gameResult);
                gradePointQuery.setWe(We_2);
                gradePointQuery.setR1(teamIntegral_2);
                Integer opponent = this.calculateRn(gradePointQuery);
                opponentIntegral.setIntegral(opponent);
                resultIntegral.add(opponentIntegral);
                Boolean isWIn_2 = false;
                if(new BigDecimal(GradePointsConstants.RESULT_WIN).compareTo(new BigDecimal(1.0 - gameResult)) == 0){
                    isWIn_2 = true;
                }
                this.updateTeamGrade(opponentIntegral.getId(), categoryId, opponent, quaryUserGradePoint.getGameScheduleId(),isWIn_2);
            }
            return resultIntegral;
        }
        return null;
    }

    @Override
    public List<GradeIntegralVo> getGradeIntegralExplain(List<Integer> categoryList) {
        List<GradeIntegralVo> gradeIntegralVos = new ArrayList<>();
        TbGameGradeIntegralExample example = new TbGameGradeIntegralExample();
        TbGameGradeIntegralExample.Criteria criteria = example.createCriteria();
        criteria.andGameTypeIn(categoryList);
        List<TbGameGradeIntegral> gameGradeIntegrals = tbGameGradeIntegralMapper.selectByExample(example);
        if(null != gameGradeIntegrals && gameGradeIntegrals.size() > 0 ){
            for(TbGameGradeIntegral gameGradeIntegral : gameGradeIntegrals){
                GradeIntegralVo vo = new GradeIntegralVo();
                BeanUtils.copyProperties(gameGradeIntegral,vo);
                vo.setCategoryId(gameGradeIntegral.getGameType());
                gradeIntegralVos.add(vo);
            }
        }
        return gradeIntegralVos;
    }

    @Override
    public RespUserGradeIntegralList getUserGradeIntegral(Integer uid,List<Integer> categoryList) {
        RespUserGradeIntegralList respUserGradeIntegralList = new RespUserGradeIntegralList();
        boolean isfirsteval_tennis = false;
        boolean isfirsteval_badminton = false;
        if(null != categoryList && categoryList.size() > 0){
            List<RespUserGradeIntegral> userGradeIntegralList = new ArrayList<>();
            for(Integer categoryId : categoryList){
                RespUserGradeIntegral userGradeIntegral = new RespUserGradeIntegral();
                UserFLScoreEntity userFLScoreEntity = gameLevelScoreApi.queryUserFLScoreEntity(uid,categoryId);
                if(null != userFLScoreEntity){
                    if(categoryId == GameConstants.CATEGORY_ID_BADMINTON){
                        isfirsteval_badminton = userFLScoreEntity.getIsFirstEval();
                    }else if(categoryId == GameConstants.CATEGORY_ID_TENNIS){
                        isfirsteval_tennis = userFLScoreEntity.getIsFirstEval();
                    }
                    TbGameGradeIntegral gameGradeIntegral = this.getMinLevelByIntegral(categoryId, (int)Math.round(userFLScoreEntity.getFLScore()));
                    userGradeIntegral.setIntegral(userFLScoreEntity.getFLScore().intValue() == 0 ? 1000 : (int) Math.round(userFLScoreEntity.getFLScore()));//四舍五入
                    userGradeIntegral.setGradeIcon(gameGradeIntegral.getGradeIcon());
                    userGradeIntegral.setLevel(gameGradeIntegral.getLevel());
                    userGradeIntegral.setLable(gameGradeIntegral.getLable());
                    userGradeIntegral.setRemark(gameGradeIntegral.getRemark());
                    userGradeIntegral.setIsSetted(!userFLScoreEntity.getIsFirstEval());
                    userGradeIntegral.setCategoryId(userFLScoreEntity.getCategoryId());
                    userGradeIntegral.setIsEval(userFLScoreEntity.getIsEval());
                    userGradeIntegral.setIsReal(userFLScoreEntity.getIsEval() ^ 1);
                    List<Double> scoreRange = userFLScoreEntity.getEvalScoreRange();
                    if(null != scoreRange && scoreRange.size() == 2){
                        Integer minIntegral = (int)Math.round(scoreRange.get(0));
                        Integer maxIntegral = (int)Math.round(scoreRange.get(1));
                        Double minLevel = this.getMinLevelByIntegral(categoryId, minIntegral).getLevel();
                        Double maxLevel = this.getMinLevelByIntegral(categoryId, maxIntegral).getLevel();
                        if(minIntegral.intValue() != 1000){
                            minLevel += 1;
                        }
                        //处理自评分数范围上下限一致时，下限等级处理出错的情况
                        if(minLevel > maxLevel){
                            minLevel = maxLevel;
                            userGradeIntegral.setIsEval(0);
                        }
                        userGradeIntegral.setMinLevel(minLevel);
                        userGradeIntegral.setMaxLevel(maxLevel);
                    }
                }

                /**
                 *  获取个人比赛总场次、胜场数、胜率
                 */
                TbUserGameCollectExample example = new TbUserGameCollectExample();
                TbUserGameCollectExample.Criteria criteria = example.createCriteria();
                criteria.andGameCategoryIdEqualTo(categoryId);
                criteria.andUidEqualTo(uid);
                List<TbUserGameCollect> tbUserGameCollectList = tbUserGameCollectMapper.selectByExample(example);
                Float gameScheduleNum = 0f;
                Float winGameScheduleNum = 0f;
                Double winRate = 0.0;
                if(null != tbUserGameCollectList && tbUserGameCollectList.size() > 0 ) {
                    TbUserGameCollect userGameCollect = tbUserGameCollectList.get(0);
                    gameScheduleNum = userGameCollect.getGameScheduleNum().floatValue();
                    winGameScheduleNum = userGameCollect.getWinGameScheduleNum().floatValue();
                    if (gameScheduleNum > 0) {
                        winRate = new Double(winGameScheduleNum / gameScheduleNum);
                    }
                }
                userGradeIntegral.setGameScheduleNum(gameScheduleNum.intValue());
                userGradeIntegral.setWinGameScheduleNum(winGameScheduleNum.intValue());
                userGradeIntegral.setWinRate(winRate);
                userGradeIntegralList.add(userGradeIntegral);
            }
            Boolean isFirstEval = isfirsteval_tennis && isfirsteval_badminton;
            respUserGradeIntegralList.setIsFirstEval(isFirstEval);
            respUserGradeIntegralList.setUserGradeIntegralList(userGradeIntegralList);
        }
        return respUserGradeIntegralList;
    }

    @Override
    public TbGameGradeIntegral getMinLevelByIntegral(Integer categoryId, Integer integral) {
        /**
         * 判断等级分是否超过系统规定
         * 范围：网球 1000 —— 5999 羽毛球/篮球/足球 1000 —— 10999
         */
        Integer minValue = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_SMALLBALL;
        Integer maxValue = GradePointsConstants.INTEGRAL_MAXVALUE_FOR_NOT_TENNIS;
        if(categoryId == GameConstants.CATEGORY_ID_TENNIS){
            maxValue = GradePointsConstants.INTEGRAL_MAXVALUE_FOR_TENNIS;
        }
        if(integral < minValue){
            integral = minValue;
        }
        if(integral > maxValue){
            integral = maxValue;
        }
        TbGameGradeIntegralExample tbGameGradeIntegralExample = new TbGameGradeIntegralExample();
        TbGameGradeIntegralExample.Criteria criteria = tbGameGradeIntegralExample.createCriteria();
        criteria.andGameTypeEqualTo(categoryId);
        criteria.andLimitValueLessThanOrEqualTo(integral);
        criteria.andMaxValueGreaterThanOrEqualTo(integral);
        TbGameGradeIntegral gameGradeIntegral = new TbGameGradeIntegral();
        List<TbGameGradeIntegral> gameGradeIntegrals = tbGameGradeIntegralMapper.selectByExample(tbGameGradeIntegralExample);
        if (null != gameGradeIntegrals && gameGradeIntegrals.size() > 0 ){
            gameGradeIntegral = gameGradeIntegrals.get(0);
        }
        return gameGradeIntegral;
    }

    @Override
    public void evalOwnFLScore(Integer uid, Double score, Integer categoryId) {
        gameLevelScoreApi.evalOwnFLScore(uid,score,categoryId);
    }

    /**
     *
     *  计算初始化积分
     *
     * */
    private Integer getUserIntegralTemp(Integer uid, Integer categoryId, Double level){
        Integer userIntegral = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_SMALLBALL;
        TbUserIntegralExample tbUserIntegralExample = new TbUserIntegralExample();
        TbUserIntegralExample.Criteria criteria = tbUserIntegralExample.createCriteria();
        criteria.andUserIdEqualTo(uid);
        criteria.andGameCategoryIdEqualTo(categoryId);
        criteria.andFlagEqualTo(GradePointsConstants.YES);
        List<TbUserIntegral> IntegralList =  tbUserIntegralMapper.selectByExample(tbUserIntegralExample);
        if (null != IntegralList && IntegralList.size() == 1){
            TbUserIntegral tbUserIntegral = IntegralList.get(0);
            userIntegral = tbUserIntegral.getIntegral();
        }else {
            if (level > 0.0) {
                userIntegral = (int)(level * userIntegral);
            }
        }
        return userIntegral;
    }

    /**
     * integral 用户对象信息
     * quaryUserGradePoint 每一场结束以后,记录用户相关信息的对象
     * gradePointQuery 积分计算基本对象
     * resultIntegral 需要变化的对象,返回
     *
     * */
    private void updateUserIntegral(GradeIntegral integral, QuaryUserGradePoint quaryUserGradePoint, GradePointQuery gradePointQuery, List<GradeIntegral> resultIntegral, Boolean isSelf){
        Integer uid = integral.getId();

        //判断是否为某个用户计算等级分，每天一次, 存在的话,不进行计算
        if(gradeIntegralCacheDao.isUserGradeFlag(uid, quaryUserGradePoint.getCategoryId())){
            return;
        }
        double tempOpp = quaryUserGradePoint.getGradePointLevel() >0.0?quaryUserGradePoint.getGradePointLevel():1;
        int gradeIntegral = (int)(tempOpp*GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_SMALLBALL);

        //获取当前用户的明分
        TbUserIntegral curTbUserIntegral = curTbUserIntegral(uid, quaryUserGradePoint.getCategoryId());

        //判断用户端明分是否有效,满足以下条件 (等级相同 + 积分有效)
        if(null!=curTbUserIntegral && curTbUserIntegral.getFlag().intValue() == GradePointsConstants.YES && curTbUserIntegral.getLevel().doubleValue() == quaryUserGradePoint.getGradePointLevel().doubleValue()){
            //设置的当前用户的R1
            gradePointQuery.setR1(integral.getIntegral());
            gradeIntegral = this.calculateRn(gradePointQuery);
            double temp = 0.00;
            if (quaryUserGradePoint.getCategoryId() == GameConstants.CATEGORY_ID_BADMINTON) {
                temp = gradeIntegral/1000 + 0.00;
            }else if (quaryUserGradePoint.getCategoryId() == GameConstants.CATEGORY_ID_TENNIS) {
                temp = (gradeIntegral/500) * 0.50;
            }
            BigDecimal b= new  BigDecimal(temp);
            curTbUserIntegral.setLevel(b.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue());
            curTbUserIntegral.setIntegral(gradeIntegral);
            tbUserIntegralMapper.updateByPrimaryKeySelective(curTbUserIntegral);
        }else{
            //校验
            TbGradeStatisticsExample example = new TbGradeStatisticsExample();
            TbGradeStatisticsExample.Criteria criteria = example.createCriteria();
            criteria.andCategoryidEqualTo(quaryUserGradePoint.getCategoryId());
            criteria.andUidEqualTo(uid);
            criteria.andLevelEqualTo(quaryUserGradePoint.getGradePointLevel());
            List<TbGradeStatistics>  temps = tbGradeStatisticsMapper.selectByExample(example);
            if (null!=temps && temps.size()>0) {
                if (temps.get(0).getScore() > gradeIntegral) {
                    gradeIntegral = temps.get(0).getScore();
                }
            }

            //为对手设置R1值
            gradePointQuery.setR1(gradeIntegral);
            gradeIntegral =  this.calculateRn(gradePointQuery);

            //更新用户某栏目下的暗分 \ 刷新明分
            if (isSelf) {
                this.updateScore(curTbUserIntegral, uid,quaryUserGradePoint.getCategoryId(), quaryUserGradePoint.getGradePointLevel(), gradeIntegral, quaryUserGradePoint.getGameResult().intValue() == GameConstants.SCHEDULE_WIN.intValue()? quaryUserGradePoint.getOpponentUserIDs():null);
            }else {
                this.updateScore(curTbUserIntegral, uid,quaryUserGradePoint.getCategoryId(), quaryUserGradePoint.getGradePointLevel(), gradeIntegral, quaryUserGradePoint.getGameResult().intValue() == GameConstants.SCHEDULE_LOSE.intValue()? quaryUserGradePoint.getSelfUserIDs():null);
            }

        }
        integral.setIntegral(gradeIntegral);
        resultIntegral.add(integral);

        /**
         * 更新用户等级分表
         */
        this.updateUserGrade(integral.getId(),quaryUserGradePoint.getCategoryId(),gradeIntegral);

        /**
         * 记录个人等级分历史数据
         */
        TbIntegralUserHistory history = new TbIntegralUserHistory();
        history.setUserId(uid);
        history.setCategoryid(quaryUserGradePoint.getCategoryId());
        history.setIntegral(gradeIntegral);
        history.setGameId(quaryUserGradePoint.getGameScheduleId());
        this.insertUserHistoryIntegral(history);
    }


    @Override
    public UserGradeIntegral getUserGradeInfo(Integer uid, Integer categoryId) {
        UserGradeIntegral userGradeIntegral = new UserGradeIntegral();
        TbUserIntegralExample example = new TbUserIntegralExample();
        TbUserIntegralExample.Criteria criteria = example.createCriteria();
        criteria.andGameCategoryIdEqualTo(categoryId);
        criteria.andUserIdEqualTo(uid);
        List<TbUserIntegral> userIntegralList = tbUserIntegralMapper.selectByExample(example);
        if (null != userIntegralList && userIntegralList.size() > 0){
            TbUserIntegral userIntegral = userIntegralList.get(0);
            userGradeIntegral.setIntegral(userIntegral.getIntegral());
            userGradeIntegral.setLevel(userIntegral.getLevel());
            userGradeIntegral.setGrade(userIntegral.getLevel().toString());
            userGradeIntegral.setGradeIcon(userIntegral.getIcon());
        }else{
            Integer integral = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_SMALLBALL;
            userGradeIntegral = this.getGradeByIntegral(categoryId,integral);
            /**
             * 初始化用户数据
             */
            this.initUserGradeIntegral(uid,categoryId,null);
        }
        return userGradeIntegral;
    }

    @Override
    public UserGradeIntegral getTeamGradeInfo(Integer uid, Integer categoryId) {
        UserGradeIntegral userGradeIntegral = new UserGradeIntegral();
        TbTeamIntegralExample example_team = new TbTeamIntegralExample();
        TbTeamIntegralExample.Criteria criteria = example_team.createCriteria();
        /**
         * 获取用户所加入的俱乐部中等级分最高的等级信息
         */
        List<Integer> clubIds = baseService.getClubIdsByUid(uid, categoryId);
        if(null != clubIds && clubIds.size() > 0){
            criteria.andTeamIdIn(clubIds);
            criteria.andFlagEqualTo(GradePointsConstants.REAL_SCORE);
            example_team.setOrderByClause("integral");
            List<TbTeamIntegral> teamIntegralList = tbTeamIntegralMapper.selectByExample(example_team);
            if(null != teamIntegralList && teamIntegralList.size() > 0 ){
                TbTeamIntegral teamIntegral = teamIntegralList.get(0);
                userGradeIntegral.setGrade(teamIntegral.getLevel().toString());
                userGradeIntegral.setGradeIcon(teamIntegral.getIcon());
                userGradeIntegral.setIntegral(teamIntegral.getIntegral());
            }else{
                Integer teamIntegral = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_BIGBALL;
                userGradeIntegral.setIntegral(teamIntegral);
                UserGradeIntegral teamGradeInfo = this.getGradeByIntegral(categoryId, teamIntegral);
                userGradeIntegral.setGrade(teamGradeInfo.getGrade());
                userGradeIntegral.setGradeIcon(teamGradeInfo.getGradeIcon());
            }
        }else{
            Integer teamIntegral = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_BIGBALL;
            userGradeIntegral.setIntegral(teamIntegral);
            UserGradeIntegral teamGradeInfo = this.getGradeByIntegral(categoryId, teamIntegral);
            userGradeIntegral.setGrade(teamGradeInfo.getGrade());
            userGradeIntegral.setGradeIcon(teamGradeInfo.getGradeIcon());
        }
        return userGradeIntegral;
    }

    @Override
    public Integer getTeamIntegral(Integer teamId, Integer categoryId) {
        Integer teamIntegral = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_BIGBALL;
        TbTeamIntegralExample tbTeamIntegralExample = new TbTeamIntegralExample();
        TbTeamIntegralExample.Criteria criteria = tbTeamIntegralExample.createCriteria();
        criteria.andTeamIdEqualTo(teamId);
        criteria.andGameCategoryIdEqualTo(categoryId);
        List<TbTeamIntegral> IntegralList = tbTeamIntegralMapper.selectByExample(tbTeamIntegralExample);
        if (null != IntegralList && IntegralList.size() == 1){
            TbTeamIntegral tbTeamIntegral = IntegralList.get(0);
            teamIntegral = tbTeamIntegral.getIntegral();
        }else if(null == IntegralList || IntegralList.size() == 0){
            teamIntegral = this.initTeamGradeIntegral(teamId,categoryId);
        }
        return teamIntegral;
    }

    /**
     * 更新用户等级分,并记录每次变更
     */
    private void updateUserGrade(Integer uid, Integer categoryId, Integer integral) {
        TbUserIntegralExample example = new TbUserIntegralExample();
        TbUserIntegralExample.Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(uid);
        TbUserIntegral tbUserIntegral = new TbUserIntegral();
        tbUserIntegral.setUserId(uid);
        tbUserIntegral.setGameCategoryId(categoryId);
        tbUserIntegral.setIntegral(integral);
        /**
         * 获取等级分对应图标
         */
        UserGradeIntegral userGradeIntegral = this.getGradeByIntegral(categoryId,integral);
        tbUserIntegral.setIcon(userGradeIntegral.getGradeIcon());
        tbUserIntegralMapper.updateByPrimaryKeySelective(tbUserIntegral);
    }

    @Override
    public UserGradeIntegral getGradeInfo(Integer uid, Integer categoryId) {
        UserGradeIntegral userGradeIntegral = new UserGradeIntegral();
        /**
         * 个人（小球）等级信息
         */
        if(categoryId == GameConstants.CATEGORY_ID_TENNIS || categoryId == GameConstants.CATEGORY_ID_BADMINTON){
            userGradeIntegral = this.getUserGradeInfo(uid, categoryId);
        /**
         *  团体（大球）等级信息
         */
        }else if(categoryId == GameConstants.CATEGORY_ID_FOOTBALL || categoryId == GameConstants.CATEGORY_ID_BASKETBALL){
            userGradeIntegral = this.getTeamGradeInfo(uid,categoryId);
        }
        return userGradeIntegral;
    }

    @Override
    public UserGradeIntegral getGradeByIntegral(Integer categoryId,Integer integral){
        /**
         * 判断等级分是否超过系统规定
         * 范围：1000 —— 5999
         */
        Integer minValue = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_SMALLBALL;
        Integer maxValue = GradePointsConstants.INTEGRAL_MAXVALUE;
        if(integral < minValue){
            integral = minValue;
        }
        if(integral > maxValue){
            integral = maxValue;
        }
        TbGameGradeIntegralExample tbGameGradeIntegralExample = new TbGameGradeIntegralExample();
        TbGameGradeIntegralExample.Criteria criteria = tbGameGradeIntegralExample.createCriteria();
        criteria.andGameTypeEqualTo(categoryId);
        criteria.andLimitValueLessThanOrEqualTo(integral);
        criteria.andMaxValueGreaterThanOrEqualTo(integral);
        UserGradeIntegral userGradeIntegral = new UserGradeIntegral();
        userGradeIntegral.setIntegral(integral);
        List<TbGameGradeIntegral> gameGradeIntegrals = tbGameGradeIntegralMapper.selectByExample(tbGameGradeIntegralExample);
        if (null != gameGradeIntegrals && gameGradeIntegrals.size() == 1){
            TbGameGradeIntegral gameGradeIntegral = gameGradeIntegrals.get(0);
            userGradeIntegral.setGrade(gameGradeIntegral.getGrade());
            userGradeIntegral.setGradeIcon(gameGradeIntegral.getGradeIcon());
            userGradeIntegral.setLevel(gameGradeIntegral.getLevel().doubleValue());
            userGradeIntegral.setStars(gameGradeIntegral.getStars());
        }
        return userGradeIntegral;
    }

    /**************************************************以下方法为了计算等级分，不对外公开*********************************************************************************************/

    /**
     * 计算We
     */
    private Double calulateWe(Double myGrade, Double opponentGrade) {
        /**
         * We = 1/(1+10^((R2-R1)/400)) (R1为己方等级分，R2为对方等级分)
         */
        Double result_value = 0.0;
        if (null != myGrade && null != opponentGrade){
            if (myGrade >= 0.0 && opponentGrade >= 0.0) {
                Double r = 1 / (1 + Math.pow(10, (opponentGrade - myGrade) / 400));
                result_value = new BigDecimal(r).setScale(3,BigDecimal.ROUND_HALF_UP).doubleValue();
            }
        }
        return result_value;
    }

    /**
     * 计算足球的比分指数
     */
    private int calculateG(Integer categoryId, String recordScore) {
        if (null == recordScore || categoryId != GameConstants.CATEGORY_ID_FOOTBALL){
            return 1;
        }
        String[] scores = recordScore.split(":");
        try {
            if(scores.length == 2 ){
                Integer i1 = Integer.parseInt(scores[0]);
                Integer i2 = Integer.parseInt(scores[1]);
                Integer p = Math.abs(i1-i2);
                return (11+p)/8;
            }
        }catch (Exception e){
            logger.info("传入的比分不符合既定规则：比如 1:2");
        }
        return 0;
    }

    /**
     * 计算Rn
     */
    private Integer calculateRn(GradePointQuery gradePointQuery) {
        /**
         * 计算等级分：Rn = R1+K*G*(Rm-R1)/2000*(W-We)
         * 参数说明：
         *        Rn：赛后等级积分(Rn >= 1000)
         *        R1: 赛前等级分
         *        K： 升降指数 （不同的项目有不同的K值）,暂时默认 为10
         *        G： 比分指数(足球G=(11+P)/8,P为净胜球数，其他为1)
         *        Rm: (羽毛球9000，其他为7000)
         *        W:  比赛结果（胜 1、平 0.5、负 0）
         *        We: 赛前双方等级分预期结果
         *            We = 1/(1+10^((R2-R1)/400)) (R1为己方等级分，R2为对方等级分)
         *
         */
        Integer R1 = gradePointQuery.getR1();
        Integer k = gradePointQuery.getK();
        Integer G = gradePointQuery.getG();
        Integer Rm = gradePointQuery.getRm();
        Double W = gradePointQuery.getW();
        Double We = gradePointQuery.getWe();
        Integer Rn = new BigDecimal(R1+k*G*(Rm - R1)/2000*(W - We)).setScale(3,BigDecimal.ROUND_HALF_UP).intValue();
        if (Rn < GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_SMALLBALL) {
            Rn = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_SMALLBALL;
        }
        return Rn;
    }

    /**
     * 获取当前用户的明分(在等级分表中记录的就是明分)
     */
    private TbUserIntegral curTbUserIntegral(Integer uid, Integer categoryId) {
        TbUserIntegralExample example = new TbUserIntegralExample();
        TbUserIntegralExample.Criteria criteria  = example.createCriteria();
        criteria.andUserIdEqualTo(uid);
        criteria.andGameCategoryIdEqualTo(categoryId);
        List<TbUserIntegral> userIntegralList = tbUserIntegralMapper.selectByExample(example);
        if (userIntegralList.size() > 0){
            return userIntegralList.get(0);
        }
        return null;
    }

    /**
     * 更新统计表的等级分，如果等级分变为有效分的话把用户等级分表设置为明分
     */
    private Integer updateScore(TbUserIntegral curTbUserIntegral, Integer uid, Integer categoryId,Double level,Integer integral,List<Integer> uids) {
        TbGradeStatisticsExample example = new TbGradeStatisticsExample();
        TbGradeStatisticsExample.Criteria criteria = example.createCriteria();
        criteria.andCategoryidEqualTo(categoryId);
        criteria.andUidEqualTo(uid);
        criteria.andLevelEqualTo(level);
        List<TbGradeStatistics> tbGradeStatisticsList = tbGradeStatisticsMapper.selectByExample(example);
        Gson gson = new Gson();
        if(null == curTbUserIntegral){
            //初始化用户等级分
            this.initUserGradeIntegral(uid,categoryId,level.intValue() * 1000);
        }


        if(tbGradeStatisticsList.size() > 0){
            TbGradeStatistics tbGradeStatistics = tbGradeStatisticsList.get(0);
            tbGradeStatistics.setScore(integral);

            //将不一样的用户插入到
            List<Integer> ids = gson.fromJson(tbGradeStatistics.getUids(), new TypeToken<List<Integer>>() {}.getType());
            if (null!=ids && ids.size()>0 && null!=uids && uids.size() > 0){
                for(Integer id : uids ) {
                    if (!ids.contains(id)) {
                        ids.add(id);
                    }
                }
            }else {
                if (null!=uids && uids.size()>0){
                    if(null == ids){
                        ids = new ArrayList<>();
                    }
                    ids.addAll(uids);
                }
            }

            tbGradeStatistics.setUids(gson.toJson(ids));
            if (null != ids && ids.size() >= GradePointsConstants.WIN_TIMES) {
                if (null != curTbUserIntegral && curTbUserIntegral.getIntegral() <= integral) {

                    //根据积分来计算当前的等级
                    double temp = 0.00;
                    if (categoryId == GameConstants.CATEGORY_ID_BADMINTON) {
                        temp = integral/1000 + 0.00;
                    }else if (categoryId == GameConstants.CATEGORY_ID_TENNIS) {
                        temp = (integral/500) * 0.50;
                    }
                    BigDecimal b= new  BigDecimal(temp);
                    level = b.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();

                    //更新用户的明分
                    this.setTrueFlag(curTbUserIntegral, level, integral);

                    //更新记录表所有等级为暗分
                    TbGradeStatisticsExample example1 = new TbGradeStatisticsExample();
                    TbGradeStatisticsExample.Criteria criteria1 = example1.createCriteria();
                    criteria1.andCategoryidEqualTo(categoryId);
                    criteria1.andUidEqualTo(uid);
                    TbGradeStatistics passTbGradeStatistics = new TbGradeStatistics();
                    passTbGradeStatistics.setFlag(GradePointsConstants.NO);
                    tbGradeStatisticsMapper.updateByExampleSelective(passTbGradeStatistics, example1);

                    //更新记录表当前等级为明分
                    tbGradeStatistics.setFlag(GradePointsConstants.YES);
                }
            }
            //更新分数
            tbGradeStatisticsMapper.updateByPrimaryKeySelective(tbGradeStatistics);
        }else{
            TbGradeStatistics tbGradeStatistics = new TbGradeStatistics();
            tbGradeStatistics.setUid(uid);
            tbGradeStatistics.setScore(integral);
            tbGradeStatistics.setCategoryid(categoryId);
            tbGradeStatistics.setLevel(level);
            tbGradeStatistics.setUids(gson.toJson(uids));
            tbGradeStatisticsMapper.insertSelective(tbGradeStatistics);

        }
        return integral;
    }

    /**
     * 把某个用户某个栏目下等级分设置为有效
     */
    private void setTrueFlag(TbUserIntegral curTbUserIntegral,Double newLevel,Integer newIntegral) {
        curTbUserIntegral.setLevel(newLevel);
        curTbUserIntegral.setIntegral(newIntegral);
        curTbUserIntegral.setFlag(GradePointsConstants.YES);
        tbUserIntegralMapper.updateByPrimaryKeySelective(curTbUserIntegral);
    }

    /**
     * 初始化用户等级积分
     */
    private Integer initUserGradeIntegral(Integer uid, Integer categoryId,Integer integral) {
        if(null == integral){
            integral = GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_SMALLBALL;
        }
        TbUserIntegral tbUserIntegral = new TbUserIntegral();
        tbUserIntegral.setIntegral(integral);
        tbUserIntegral.setLevel(integral.doubleValue()/1000);
        tbUserIntegral.setGameCategoryId(categoryId);
        tbUserIntegral.setUserId(uid);
        tbUserIntegral.setFlag(GradePointsConstants.NO);
        /**
         * 获取等级分对应图标
         */
        UserGradeIntegral userGradeIntegral = this.getGradeByIntegral(categoryId,integral);
        tbUserIntegral.setIcon(userGradeIntegral.getGradeIcon());
        tbUserIntegralMapper.insertSelective(tbUserIntegral);
        return integral;
    }

    /**
     * 初始化队伍等级积分
     */
    private Integer initTeamGradeIntegral(Integer teamId, Integer categoryId) {
        Integer integral =  GradePointsConstants.GRADE_MIN_GRADE_POINT_FOR_BIGBALL;
        TbTeamIntegral tbTeamIntegral = new TbTeamIntegral();
        tbTeamIntegral.setTeamId(teamId);
        tbTeamIntegral.setIntegral(integral);
        tbTeamIntegral.setGameCategoryId(categoryId);
        tbTeamIntegral.setLevel(GradePointsConstants.GRADE_MIN_TEAM_LEVEL);
        /**
         * 初次设置打赢的队伍数为0，等级分为暗分
         */
        tbTeamIntegral.setTimes(0);
        /**
         * 设置等级图片
         */
        UserGradeIntegral userGradeIntegral = this.getGradeByIntegral(categoryId, integral);
        tbTeamIntegral.setIcon(userGradeIntegral.getGradeIcon());
        tbTeamIntegral.setFlag(GradePointsConstants.FALSE_SCORE);
        tbTeamIntegralMapper.insertSelective(tbTeamIntegral);
        return integral;
    }

    /**
     * 记录历史用户等级分
     */
    private void insertUserHistoryIntegral(TbIntegralUserHistory history) {
        TbIntegralUserHistory integralUserHistory = new TbIntegralUserHistory();
        BeanUtils.copyProperties(history,integralUserHistory);
        tbIntegralUserHistoryMapper.insertSelective(integralUserHistory);
    }

    /**
     * 记录历史团队等级分
     */
    private void insertTeamHistoryIntegral(TbIntegralTeamHistory history) {
        TbIntegralTeamHistory integralTeamHistory = new TbIntegralTeamHistory();
        BeanUtils.copyProperties(history,integralTeamHistory);
        tbIntegralTeamHistoryMapper.insertSelective(integralTeamHistory);
    }

    /**
     * 更新队伍等级分,并记录每次变更
     */
    private void updateTeamGrade(Integer teamId, Integer categoryId, Integer gradeIntegral, Integer gameId,Boolean isWin) {
        TbTeamIntegralExample example = new TbTeamIntegralExample();
        TbTeamIntegralExample.Criteria criteria = example.createCriteria();
        criteria.andTeamIdEqualTo(teamId);
        criteria.andGameCategoryIdEqualTo(categoryId);
        List<TbTeamIntegral> integrals = tbTeamIntegralMapper.selectByExample(example);
        TbTeamIntegral teamIntegral = integrals.get(0);
        teamIntegral.setIntegral(gradeIntegral);
        UserGradeIntegral grade =this.getGradeByIntegral(categoryId, gradeIntegral);
        teamIntegral.setLevel(grade.getLevel());
        teamIntegral.setIcon(grade.getGradeIcon());
        /**
         * 判断该队赢了多少场比赛，赢了8场就把等级分设置为明分
         */
        if(isWin){
            Integer winTimes = teamIntegral.getTimes() + 1;
            teamIntegral.setTimes(winTimes);
            /**
             * 比赛赢的次数为 TEAM_WIN_TIMES 次,设置为明分了
             */
            if(winTimes >= GradePointsConstants.TEAM_WIN_TIMES){
                teamIntegral.setFlag(GradePointsConstants.REAL_SCORE);
            }
        }
        tbTeamIntegralMapper.updateByPrimaryKeySelective(teamIntegral);
        TbIntegralTeamHistory history = new TbIntegralTeamHistory();
        history.setIntegralId(teamIntegral.getId());
        history.setTeamId(teamIntegral.getTeamId());
        history.setCategoryid(categoryId);
        history.setIntegral(gradeIntegral);
        history.setGameId(gameId);
        this.insertTeamHistoryIntegral(history);
    }

    /*******************************************************以上方法为了计算等级分，不对外公开****************************************************************************************************************/

    /******************************************************下面的接口根据需求的调整已经废弃，下一版本可能删除掉 **************************************************************************/
    @Override
    public UserGradeIntegral getSingleGrade(Integer level,Integer categoryId) {
        TbGameGradeIntegral gameGradeIntegral = new TbGameGradeIntegral();
        UserGradeIntegral userGradeIntegral = new UserGradeIntegral();
        if (null != gameGradeIntegral){
            BeanUtils.copyProperties(gameGradeIntegral,userGradeIntegral);
            userGradeIntegral.setIntegral(gameGradeIntegral.getLimitValue());
        }
        return userGradeIntegral;
    }

    @Override
    public Integer integralCalulate(double w, Integer we) {
        //个人单次比赛积分（PS）=（2+W-We)*系数
        Double score = 2+ w - we.doubleValue();

        return score.intValue();
    }
}
